package com.google.gwt.gfx.client.graphics;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import com.google.gwt.gfx.client.shared.Point;
import com.google.gwt.gfx.client.style.FillStyle;
import com.google.gwt.gfx.client.style.StrokeStyle;
import com.google.gwt.user.client.Element;

public abstract class LinearRing extends SimpleGraphic {

	public static LinearRing get() {
		return GraphicFactory.DEFAULT.createLinearRing();
	}

	private FillStyle fillRef;

	private Collection<Point> pointsRef = new Collection<Point>() {

		private List<Point> list = new ArrayList<Point>();

		@Override
		public boolean add(Point point) {
			if (list.add(point)) {
				append(point);
				return true;
			}
			return false;
		}

		@Override
		public boolean addAll(final Collection<? extends Point> c) {
			if (list.addAll(c)) {
				append(list);
				return true;
			}
			return false;
		}

		@Override
		public void clear() {
			if (list.size() > 0) {
				list.clear();
				update(list);
			}
		}

		@Override
		public boolean contains(Object o) {
			return list.contains(o);
		}

		@Override
		public boolean containsAll(Collection<?> c) {
			return list.containsAll(c);
		}

		@Override
		public boolean isEmpty() {
			return list.isEmpty();
		}

		@Override
		public Iterator<Point> iterator() {
			return list.iterator();
		}

		@Override
		public boolean remove(Object o) {
			if (list.remove(o)) {
				update(list);
				return true;
			}

			return false;
		}

		@Override
		public boolean removeAll(Collection<?> c) {
			if (list.removeAll(c)) {
				update(list);
				return true;
			}
			return false;
		}

		@Override
		public boolean retainAll(Collection<?> c) {
			if (list.retainAll(c)) {
				update(list);
				return true;
			}
			return false;
		}

		@Override
		public int size() {
			return list.size();
		}

		@Override
		public Object[] toArray() {
			return list.toArray();
		}

		@Override
		public <T> T[] toArray(T[] a) {
			return list.toArray(a);
		}

	};

	private StrokeStyle strokeRef;

	protected LinearRing(Element element) {
		super(element);

		fillRef = GraphicFactory.DEFAULT.createFillOf(this);
		strokeRef = GraphicFactory.DEFAULT.createStrokeOf(this);
	}

	protected abstract void append(List<Point> point);

	protected abstract void append(Point point);

	public FillStyle fill() {
		return fillRef;
	}

	public Collection<Point> points() {
		return pointsRef;
	}

	public StrokeStyle stroke() {
		return strokeRef;
	}

	protected abstract void update(List<Point> points);

}
